
#include <iostream>
#include <string>
#include <memory>

/*
    函数重载个重写的区别

    1 虚函数是基类希望派生类重新定义的函数，派生类重新定义基类虚函数的做法叫做覆盖（重写）；

    2 重载就在允许在相同作用域中存在多个同名的函数，这些函数的参数表不同。重载的概念不属于面向对象编程，编译器根据函数不同的形参表对同名函数的名称做修饰，然后这些同名函数就成了不同的函数。

    3 重载的确定是在编译时确定，是静态的；虚函数则是在运行时动态确定。


*/

/*
    C++面向对象的三大特性：封装 继承 多态
    封装：
        （1）封装就是将客观的事物抽象成类和对象，并对其中的属性和方法进行保护限制
        （2）对函数具体实现的封装，特殊属性的封装，特殊数据的封装、保护数据隐私和实现安全
    继承：
        （1）继承就是让某一个类型的对象获取另一个类型对象的属性和方法。
        （2）继承可以让现有对象或者类获取被继承类的属性和方法，并且可以对其进行功能的扩展。
        （3）继承的类称为子类、派生类，被继承的类称为基类、父类、超类等。
        （4）继承的实现一个通过继承和组合来实现。
        （5）继承一般分为：
            实现继承：实现继承是指子类继承基类的属性和方法，可以直接使用它们，无需重新编写相同的代码
            接口继承：接口继承是指基类定义了一组属性和方法的名称，但没有提供具体的实现，子类必须提供这些属性和方法的实现，基类定义纯虚函数，让子类去实现
            可视继承：可视继承通常与图形用户界面（GUI）编程相关，它表示子窗体可以继承父窗体的外观和实现代码
            
            
            
*/

/*
    new的作用：C++中的new运算符用于动态分配内存空间，它会在堆（即自由存储区）中分配一块内存，并返回该内存的地址
        （1）在堆上动态分配单个对象的内存空间。
        （2）在堆上动态分配数组的内存空间。
        （3）创建动态对象，使其在程序运行时具有灵活的生命周期。
        （4）在对象创建时进行初始化。

*/

/*
    智能指针会定维护一个共享的指向对象的指针，当共享指针使用结束后会自动调用析构函数，释放掉对象的内存空间
*/

/*
    实例化指的是从一个类或者一个模板中实例中一个具体的对象或者函数
    类是集合，代表一类对象的集合，实例化就是具体出该类中的一个对象
*/





using namespace std;

namespace TR // 实现继承
{
    
    class Father
    {
        public:
            void print()
            {
                cout << "This is my Father!" << endl;
            };
            
    };


    class Son : public Father
    {
       // 实现继承

    };

};

namespace TR1 // 接口继承,使用virtual关键字定义纯虚函数，让子类去重写，实现多态的一种手段
{
    
    class Father
    {
        public:
            Father()
            {
                cout << "构造函数" << endl;
            };

            ~Father()
            {
                cout << "析构函数" << endl;
            };

            virtual void print() = 0;
            
    };

    
    class Son : public Father
    {
       // 实现继承
        private:
            string name = "This is my son!";
        public:
            // 重写基类的print函数 ，返回值和参数要一致
            void print() override
            {
                cout << name << endl;
            }
    };

    class Mother
    {
        public:
            Mother()
            {
                cout << "构造函数" << endl;
            };
            ~Mother()
            {
                cout << "析构函数" << endl;
            };
        private:
            void log();
            void get();
        public:
            string str;
    };
    

};

namespace TR2 // 可视继承，本质上还是子类继承父类
{
    // 基类窗体
    class BaseWindow {
    public:
        void render() {
            std::cout << "Rendering base window" << std::endl;
        }
    };

    // 子窗体继承基类窗体
    class ChildWindow : public BaseWindow {
        public:
            void additionalFunction() {
                std::cout << "Performing an additional function" << std::endl;
            }
    };

};




int main(int argc, char *argv[])
{

    // 实现继承
    {   using namespace TR;
        Son * tom = new Son();
        tom->print();
        delete tom;

        int *arr = new int[7];
        delete [] arr;
    }

    cout << "******************" << endl;
    // 接口继承
    {   using namespace TR1;
        // 智能指针自动释放对象的空间
        cout << "智能指针自动释放对象的空间" << endl;
        {
            shared_ptr<Son> tom(new Son());
            tom->print();
            
        }

        cout << "******************" << endl;
        // 手动释放对象的空间
        cout << "手动释放对象的空间" << endl;
        { 
            Son * tom = new Son();
            tom->print();
            delete tom;
        }
        cout << "******************" << endl;
        // 含有纯虚函数的类不能被实例化
        {
            // 
            #if 0 // 错误的代码
            Father * David = new Father();
            David->print();
            delete David;
            #endif
        }

        {
            Mother *mom = new Mother();
            delete mom;
        }
        

    }
    
    // 可视继承，继承基窗口的渲染特性
    {
        using namespace TR2;
        ChildWindow childWindow;
        childWindow.render(); // 子窗体继承了渲染方法
        childWindow.additionalFunction();
    
    }


    return 0;
}